<?php
/**
 * Created by PhpStorm.
 * User: tandunzhao
 * Date: 2018/5/28
 * Time: 下午2:41
 */

namespace App\Http\Controllers\Api\Pay;


use App\Http\Controllers\Controller;
use App\Libs\Pay\WechatPay;
use App\Libs\SMS;
use App\Modules\Task\Models\Task;
use App\Modules\Balance\Services\BalanceService;
use App\Modules\Jobs\Services\SendTemplateMessageService;
use App\Modules\Message\Services\MessageService;
use App\Modules\Order\Services\OrderService;
use App\Modules\Task\Services\RewardService;
use App\Modules\Pay\Services\PayMerchantService;
use App\Modules\Pay\Services\PayPaymentService;
use App\Modules\Pay\Services\PayWithdrawCashService;
use App\Modules\Task\Services\TaskService;
use App\Modules\User\Models\User;
use App\Modules\User\Services\UserBillService;
use App\Modules\User\Services\UserService;
use Illuminate\Http\Request;
use DB;
use Log;

class WeChatPayController extends Controller
{

    /**
     * @apiDefine WeChatPay 微信支付
     */

    /**
     * @apiVersion 1.0.0
     * @apiDescription 微信支付下单
     * @api {POST} pay/order/create 微信支付下单
     * @apiName createOrder
     * @apiGroup WeChatPay
     *
     * @apiParam   {Number}  task_id 任务ID
     * @apiParam   {Number}  amount 支付金额
     * @apiParam   {String}  remark 备注
     *
     * @apiSuccess {String}  appId 小程序ID
     * @apiSuccess {String}  package 数据包
     * @apiSuccess {String}  nonceStr 随机串
     * @apiSuccess {String}  timeStamp 时间戳
     * @apiSuccess {String}  signType 签名方式
     * @apiSuccess {String}  paySign 签名信息
     * @apiSuccess {String}  order 订单号
     * @apiSuccessExample {json} Success-Response:
     *
     *     {
     *         "code": 0,
     *         "msg": "",
     *         "data":
     *         {
     *           "appId": "wxd678efh567hg6787",
     *           "package": "prepay_id=wx2017033010242291fcfe0db70013231072",
     *           "nonceStr": "5K8264ILTKCH16CQ2502SI8ZNMTM67VS",
     *           "timeStamp": 1490840662,
     *           "signType": "MD5",
     *           "paySign": "22D9B4E54AB1950F51E0649E8810ACD6"
     *           "order": "201805290341471601768320065670",
     *         }
     *     }
     */
    public function createOrder(Request $request) {
        if($this->isNotLogin() || !$this->getLoginUserWechatOpenId()) {
            return response()->error("NOT_LOGIN");
        }
        $task_id = $request->has('task_id') ? $request->input('task_id') : '';
        if(!is_numeric($task_id)) {
            return response()->error("PARAM_ERROR");
        }


        $payMerchant = PayMerchantService::getUsePayMerchantSource();
        if(!$payMerchant) {
            return response()->error("PAY_SOURCE_NOT_EXIST");
        }

        //输入的是钱单位元
        $amount = $request->has('amount') && $request->input('amount') ? $request->input('amount') : '';
        if(!is_numeric($amount)) {
            return response()->error("PARAM_ERROR");
        }
        if($amount <= 0) {
            return response()->error("PARAM_ERROR");
        }

        $uid = $this->getLoginUserId();

        $trade_no = date("YmdHis").hexdec(uniqid());

        //保存未支付订单
        $orderData = [
            'uid'=>$uid,
            'task_id'=>$task_id,
            'money'=>$amount,
            'trade_no'=>$trade_no,
            'pay_merchant_source'=>$payMerchant->source,
            'pay_merchant_id'=>$payMerchant->id,
            'create_ip'=>$request->getClientIp(),
        ];
        OrderService::saveUnPAIDOrder($orderData);

        //微信下单操作
        $payConfig = [];
        if($payMerchant->config_info){
            $payConfig = json_decode($payMerchant->config_info,true);
        }
        $wechatPay = WechatPay::instance($payMerchant->source, $payConfig);
        if(!$wechatPay) {
            return response()->error('PAY_SOURCE_ERROR');
        }

        $notify_url = env('OFFICIAL_PAY_CALL_BACK_URL').'/'.$payMerchant->id;

        //TODO  测试阶段全部改为一分钱
        $price = $amount * 100;
        if(in_array($uid, explode(',',env('TEST_PAY_UID')))){
            $price = 1;
        }
        //$price = 1;

        $remark = $request->has('remark') && $request->input('remark') ? $request->input('remark') : '';
        if(!$remark) {
            $remark = '帮找酬金';
        }

        $detail = '帮找酬金';
        if(is_numeric($task_id)) {
            $task = Task::getTask($task_id);
            if($task) {
                $detail = $task->title;
            }
        }

        $payData = [
            'price'=> $price,
            'create_ip'=> $request->getClientIp(),
            'openid'=> $this->getLoginUserWechatOpenId(),
            'body' => '帮找酬金',
            'detail' => $detail,
            'trade_no' => $trade_no,
            'remark' => $remark,
            'notify_url' => $notify_url,
        ];
        Log::info('微信支付下单--Official---enter--start------------ '.$uid.'=='.$price.' notify_url = '.$notify_url);
        $payResultInfo = $wechatPay->send($payData);

        if(!$payResultInfo || count($payResultInfo) == 0){
            $payResultInfo = $wechatPay->send($payData);
        }
        if(!isset($payResultInfo['appId']) || !isset($payResultInfo['package'])) {
            try{
                //自动切换支付通道
                $time = (int)date('H');
                $change = false;
                if($time <= 8 || $time>=23){
                    DB::table('pay_merchants')->update(['is_use'=>0]);
                    DB::table('pay_merchants')->where('source', 'OFFICIALPAY')->update(['is_use'=>1]);
                    $change = true;
                }
                $phone_arr = explode(',',env('TEST_PAY_ERROR_PHONE_NOTICE'));
                $content = "[帮找]".$payMerchant->source.'支付，订单号为'.$trade_no.'支付异常,异常信息:'.json_encode($payResultInfo);
                if($change){
                    $content .= ',已经切换到官方支付';
                }
                foreach ($phone_arr as $phone){
                    //发送短信
                    // SMS::send($phone,$content);
                }
                file_put_contents(date('Y-m-d').'txt',json_encode($payResultInfo),FILE_APPEND);
            }catch (\Exception $e){
            }

            return response()->error('PAY_SOURCE_ERROR');
        }

        $payResultInfo['order'] = $trade_no;

        return response()->success($payResultInfo);
    }

    /**
     * 微信支付官方回调方法
     * http://tbz.zhuishuyun.com/api/pay/order/callback/1
     */
    function wechatPayCallback(Request $request, $payMerchantId) {
        Log::info('微信支付官方回调--Official--------------- payMerchantId = '.$payMerchantId);
        $payMerchant = PayMerchantService::get($payMerchantId);
        if($payMerchant) {
            $payConfig = [];
            if($payMerchant->config_info){
                $payConfig = json_decode($payMerchant->config_info,true);
            }

            $config = [
                // 微信支付参数
                'wechat' => [
                    'debug'      => false, // 沙箱模式
                    'app_id'     => $payConfig['appid'], // 应用ID
                    'mch_id'     => $payConfig['merchant_id'], // 微信支付商户号
                    'mch_key'    => $payConfig['key'], // 微信支付密钥
                    'ssl_cer'    => $payConfig['cert_path'], // 微信证书 cert 文件
                    'ssl_key'    => $payConfig['key_path'], // 微信证书 key 文件
                    'notify_url' =>  env('OFFICIAL_PAY_CALL_BACK_URL').'/'.$payMerchant->id,
                    'cache_path' => '',// 缓存目录配置（沙箱模式需要用到）
                ]
            ];
            $pay = new \Pay\Pay($config);
            $verify = $pay->driver('wechat')->gateway('app')->verify(file_get_contents('php://input'));
            Log::info("微信支付官方回调 " . json_encode($verify));
            /*
                     * {
                     * "appid":"wxf065f7364b078a73",
                     * "bank_type":"CFT",
                     * "cash_fee":"1",
                     * "fee_type":"CNY",
                     * "is_subscribe":"N",
                     * "mch_id":"1500977641",
                     * "nonce_str":"pBnoo7zKAZ9geZfk",
                     * "openid":"oB3LO0oulGThh2nxP3mhj4PHUbmg",
                     * "out_trade_no":"201804041500331596797991726758",
                     * "result_code":"SUCCESS",
                     * "return_code":"SUCCESS",
                     * "sign":"EF7B7B621CBC970C50EEACFE8486AAB5",
                     * "time_end":"20180404150326",
                     * "total_fee":"1",
                     * "trade_type":"APP",
                     * "transaction_id":"4200000092201804041969054552"
                     * }
                     */
            $data = [];
            $data['return_code'] = 'SUCCESS';//SUCCESS/FAIL,;SUCCESS表示商户接收通知成功并校验成功
            $data['return_msg'] = 'OK';//返回信息，如非空，为错误原因：签名失败; 参数格式校验错误
            if ($verify
                && isset($verify['result_code'])
                && $verify['result_code'] == 'SUCCESS'
                && isset($verify['return_code'])
                && $verify['return_code'] == 'SUCCESS') {

                $trade_no = $verify['out_trade_no'];
                $order = OrderService::findByTradeNo($trade_no);
                if (!$order || $order->status == 'PAID') { // 如果订单不存在 或者 订单已经支付过了
                    // 告诉微信，我已经处理完了，订单没找到，别再通知我了
                } else {
                    DB::beginTransaction();
                    try {
                        $order->status = 'PAID';
                        $order->pay_end_at = date('Y-m-d H:i:s');
                        $order->transaction_id = $verify['transaction_id'];
                        $order->save(); // 保存订单

                        Log::info("微信支付官方回调 充值成功回调金额 ：" . $order->money);

                        //更新用户余额
                        BalanceService::recharge($order->uid, $order->money);
                        //更新用户流水...
                        UserBillService::addPayBill($order->uid, $order->money, $order->id, $order->task_id);
                        // 冻结用户可用余额
                        RewardService::frozen_reward($order->task_id,$order->money,0);

                        DB::commit();

                        try{
                            MessageService::addPaySucMessage($order->uid,$order->money,$order->task_id);
                        }catch (\Exception $e){
                            Log::error('addPaySucMessage failed '.$e->getCode().$e->getMessage());
                        }
                    } catch (\Exception $e){
                        Log::error("微信支付官方回调 充值成功回调金额失败日志" . $e->getMessage());
                        DB::rollback();
                        $data = [];
                    }

                }
            } else {
                $data = [];
            }
            if (!is_array($data) || count($data) <= 0) {
                return response('');
            }
            $data = $this->toXml($data);
            return response($data);
        }
        return '';
    }

    protected function toXml($data) {
        if (!is_array($data) || count($data) <= 0) {
            throw new InvalidArgumentException('convert to xml error !invalid array!');
        }
        $xml = '<xml>';
        foreach ($data as $key => $val) {
            $xml .= (is_numeric($val) ? "<{$key}>{$val}</{$key}>" : "<{$key}><![CDATA[{$val}]]></{$key}>");
        }
        return $xml . '</xml>';
    }








    /**
     * @apiVersion 1.0.0
     * @apiDescription 付款到个人
     * @api {POST} pay/company/person 付款到个人
     * @apiName companyPayPerson
     * @apiGroup WeChatPay
     *
     * @apiParam   {Number}  withdraw_cash_id 提现id.
     * @apiParam   {String}  [remark] 备注说明.
     * @apiParam   {String}  [source] 打款通道[wechat ,tl, ll].
     *
     * @apiSuccessExample {json} Success-Response:
     *
     *     {
     *         "code": 0,
     *         "msg": "",
     *         "data":
     *         {
     *         }
     *     }
     */
    function companyPayPerson(Request $request) {
//        if($this->isNotLogin()) {
//            return response()->error("NOT_LOGIN");
//        }
//        if(!$this->getLoginUserWechatOpenId()) {
//            return response()->error("NOT_LOGIN");
//        }

        $withdraw_cash_id = $request->has('withdraw_cash_id') ? $request->input('withdraw_cash_id') : '';
        if(!is_numeric($withdraw_cash_id)) {
            return response()->error("PARAM_ERROR");
        }

        $payWithdrawCash = PayWithdrawCashService::getWithdrawCash($withdraw_cash_id);
        if(!$payWithdrawCash) {
            return response()->error("PARAM_ERROR");
        }
        if(in_array($payWithdrawCash->status, PayWithdrawCashService::getWithdrawCashStatusStrList(30))) {
            //已经付款
            return response()->error("WITHDRAW_CASH_MONEY_TOO");
        }
        if(in_array($payWithdrawCash->status, PayWithdrawCashService::getWithdrawCashStatusStrList(10))
            || in_array($payWithdrawCash->status, PayWithdrawCashService::getWithdrawCashStatusStrList(40))) {
            //待打款
            //打款失败
        } else {
            return response()->error("WITHDRAW_CASH_MONEY_STATUS_ERROR");
        }


        $user = User::getUserInfo($payWithdrawCash->uid);
        if(!$user || !$user->openid) {
            return response()->error("PARAM_ERROR");
        }

        $remark = $request->has('remark') ? $request->input('remark') : '';
        $source = $request->has('source') ? $request->input('source') : '';
        if(!in_array($source, ['wechat', 'tl', 'll'])) {
            $source = 'wechat';
        }

        $payAmount = (float)($payWithdrawCash->amount - $payWithdrawCash->tallage);

        if($source == 'wechat') {
            $payAmount = intval($payAmount * 100);
            Log::info('payAmount:'.$payAmount);
            $resultData = WechatPay::companyPayToPersonWithdrawCash($user->id, $payAmount, $payWithdrawCash->id, $remark);
            if($resultData['result']) {
                try {
                    //发送提现成功 模版消息
                    SendTemplateMessageService::sendWithdrawMsg($payWithdrawCash->uid, $payWithdrawCash->amount, 'pages/user/user');
                } catch (\Exception $e) {
                    Log::error('sendWithdrawMsg failed '.$e->getCode().$e->getMessage());
                }
            } else {
                return response()->error('WITHDRAW_CASH_ERROR', $resultData['msg']);
            }
        }
        return response()->success();
    }
}